#ifndef _CRT_EVENT_H_
#define _CRT_EVENT_H_

#include <crt_core.hpp>
#include <crt_atomic.h>
#include <crt_evrbtree.h>

#ifdef __cplusplus
extern "C" {
#endif

// evoper is an action
typedef const struct timeval* ev_time_t;
// evoper_s->sock  use windows  WSASocket must IOCP
typedef struct evoper_s evoper_t;
typedef struct evsysop_s evsysop_t;
typedef struct evloop_s evloop_t;
typedef struct evaddr_s evaddr_t;
typedef unsigned char evevent;
typedef unsigned char evtype;

typedef void* (*evmem_malloc)(evloop_t* loop, size_t count, size_t size);
typedef int (*evmem_free)(evloop_t* loop, void* ptr);
typedef int (*evloop_handler)(evloop_t* loop, short event, void* ctx);
typedef int (*ev_handler)(evevent res, evoper_t* oper, evoper_t* oper_s, evevent event);

#ifndef _evaddrptr_
#define _evaddrptr_
struct evaddr_s {
    LPCSTR ptr;
    size_t len;
    USHORT port;
};
#endif // !_evaddrptr_

#define ev_none_type 0x00
// write,read,send,recv
#define ev_sock     0xE1 // tcp_sock_c
#define ev_sockpoll 0xE2 // tcp_sock_s
// recvfrom,sendto
#define ev_rsock     0xE3 // raw_sock_c
#define ev_rsockpoll 0xE4 // raw_sock_s
// recvfrom,sendto
#define ev_usock     0xE5 // udp_sock_c
#define ev_usockpoll 0xE6 // udp_sock_s
// system
#define ev_thread 0xA1
#define ev_signal 0xA2
#define ev_child  0xA3
#define ev_time   0xA4

#ifndef op_ev_none
#define op_ev_none 0x00
#endif // !op_ev_none

#ifndef op_ev_read
#define op_ev_read 0x10
#endif // !op_ev_read

#ifndef op_ev_write
#define op_ev_write 0x20
#endif // !op_ev_write

#ifndef op_ev_timer
#define op_ev_timer 0x30
#endif // !op_ev_timer

#ifndef op_ev_open
#define op_ev_open 0x40
#endif // !op_ev_open

#ifndef op_ev_connect
#define op_ev_connect 0x50
#endif // !op_ev_connect

#ifndef op_ev_accept
#define op_ev_accept 0x60
#endif // !op_ev_accept

#ifndef op_ev_close
#define op_ev_close 0x70
#endif // !op_ev_close

#ifndef op_ev_edge
#define op_ev_edge 0x10
#endif // !op_ev_edge

#ifndef op_ev_level
#define op_ev_level 0x20
#endif // !op_ev_level

///////////////////////////////////
#ifndef op_ev_success
#define op_ev_success 0x00
#endif // !op_ev_success

#ifndef op_ev_faild
#define op_ev_faild 0x01
#endif // !op_ev_faild
///////////////////////////////////

buf_len evoper_rbyte(evoper_t* oper);
buf_len evoper_wbyte(evoper_t* oper);

int evoper_read_buf(evoper_t* oper, buf_ptr buf, buf_len len);
int evoper_write_buf(evoper_t* oper, buf_ptr buf, buf_len len);

int evoper_set_msec(evoper_t* oper, crt_msec msec);
int evoper_get_msec(evoper_t* oper, crt_msec* msec);
int evoper_bind_ctx(evoper_t* oper, void* ctx);
int evoper_get_ctx(evoper_t* oper, void** ctx);
int evoper_bind_sock(evoper_t* oper, _sock_t sock);
int evoper_get_sock(evoper_t* oper, _sock_t* sock);
int evoper_bind_fd(evoper_t* oper, _fd_t fd);
int evoper_get_fd(evoper_t* oper, _fd_t* fd);
int evoper_bind_type(evoper_t* oper, evtype type);
int evoper_get_type(evoper_t* oper, evtype* type);
int evoper_bind_evloop(evoper_t* oper, evloop_t* loop);
int evoper_get_evloop(evoper_t* oper, evloop_t** evloop);
int evoper_sock(evoper_t* oper);
int evoper_pollsock(evoper_t* oper, const evaddr_t* addr, int listen);
int evoper_bind_handler(evoper_t* oper, ev_handler handler);

typedef enum { evloop_null = 0, evloop_close, evloop_running, evloop_pause } evloop_status;
int evloop_set_status(evloop_t* loop, evloop_status st);
evloop_status evloop_get_status(evloop_t* loop);
int evloop_update_time(evloop_t* loop);
int evloop_set_clock(evloop_t* loop, crt_msec msec);
int evloop_get_clock(evloop_t* loop, crt_msec* msec);

int evloop_bind_ctx(evloop_t* loop, void* ctx);
int evloop_get_ctx(evloop_t* loop, void** ctx);
int evloop_bind_mmctx(evloop_t* loop, void* mmctx);
int evloop_get_mmctx(evloop_t* loop, void** mmctx);

int evloop_add_timer(evloop_t* loop, evoper_t* oper, ev_time_t tv);
int evloop_enable_read(evloop_t* loop, evoper_t* oper, short event, socklen_t size, ev_time_t tv);
int evloop_enable_write(evloop_t* loop, evoper_t* oper, short event, socklen_t size, ev_time_t tv);
int evloop_disable_read(evloop_t* loop, evoper_t* oper);
int evloop_disable_write(evloop_t* loop, evoper_t* oper);
int evloop_canncel(evloop_t* loop, evoper_t* oper);
int evloop_open(evoper_t* oper, const evaddr_t* addr, ev_time_t tv);
int evloop_poll(evoper_t* oper, unsigned int ls);
int evloop_add_connect(evoper_t* oper, const evaddr_t* addr, ev_time_t tv);
int evloop_del_connect(evoper_t* oper);
int evloop_alloc_evoper(evloop_t* loop, evoper_t* oper);
int evloop_dealloc_evoper(evloop_t* loop, evoper_t* oper);

int evloop_init(evloop_t* loop, int size, int flag);
int evloop_uninit(evloop_t* loop);

int evloop_run(evloop_t* loop, crt_msec msec);
int evloop_stop(evloop_t* loop);

int evoper_alloc(evoper_t** oper, void* ctx, void* (*alloc)(void* ctx, size_t size));
int evoper_free(evoper_t* oper, void* ctx, int (*free)(void* ctx, void* ptr));

int evloop_alloc(evloop_t** loop, void* ctx, void* (*alloc)(void* ctx, size_t size));
int evloop_free(evloop_t* loop, void* ctx, int (*free)(void* ctx, void* ptr));

int evloop_bind_memory(evloop_t* loop, evmem_malloc malloc, evmem_free free, void* mmctx);
int evloop_bind_event(evloop_t* loop, evloop_handler handler);

#ifdef __cplusplus
}
#endif

#endif
